package com.dsg.aspect;

import com.dsg.common.security.SystemAuthorizingUser;
import com.dsg.entity.system.DsgSysOptLog;
import com.dsg.service.system.IDsgSysOptLogService;
import com.dsg.service.system.impl.DsgSysOptLogServiceImpl;
import com.powerbridge.core.constants.MessageConstants;
import com.powerbridge.core.dto.AjaxResult;
import com.powerbridge.core.util.ServletUtils;
import com.powerbridge.core.util.UUIDGenerator;
import com.powerbridge.core.util.toolbox.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.support.WebApplicationContextUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author system
 * @version 1.0.0
 * @ClassName ControllerMethodInterceptor
 * @Description 拦截器（用户行为日志）
 * @Date 2020年7月11日 上午9:57:31
 */

@Aspect
@Component
@Slf4j
public class SystemLogAspect {

    @Pointcut(value = "execution(* com.dsg.controller..*(..))")
    private void systemLog() {
    }

    @Autowired
    private IDsgSysOptLogService dsgSysOptLogService;

    //无需记录的url清单（主要是系统自动调用,比如取基础参数下拉）
    private static List<String> excludeUri = new ArrayList<>();

    static {
        excludeUri.add("/api/login");
        excludeUri.add("/api/getCompanyInfo");
        excludeUri.add("/system/login");
        excludeUri.add("/system/logout");
        excludeUri.add("/system/dsgSysParameter/getSysParameter");
    }

    @Around("systemLog()")
    public Object arround(ProceedingJoinPoint pjp) throws Throwable {
        //调用者应用url
        String url = ServletUtils.getRequest().getRequestURI();

        if (excludeUri.contains(url)) {
            return pjp.proceed();
        }
        SystemAuthorizingUser sysUser = com.dsg.common.util.SingletonLoginUtils.getSystemUser();
        if (sysUser == null) {
            throw new Exception("用戶未登錄!");
        }
        //调用者ip
        String ip = ServletUtils.getIpAddr();
        //调用者用户id
        String userId = sysUser.getUserId();

        //类型 88 代表GSD,-1代表异常
        int type = 88;
        long t1 = System.currentTimeMillis();
        try {
            Object result = pjp.proceed();
            long t2 = System.currentTimeMillis();
            String msg = "";
            if (result != null) {
                if (result instanceof AjaxResult) {
                    msg = ((AjaxResult) result).getMessage();
                } else {
                    msg = "ok";
                }
            }
            getSystemLog(ip, userId, url, type, msg, (t2 - t1));
            return result;
        } catch (Throwable throwable) {
            long t2 = System.currentTimeMillis();
            AjaxResult ajaxResult = new AjaxResult(MessageConstants.PB_STATUS_FAIL, throwable.getMessage());
            getSystemLog(ip, userId, url, -1, ajaxResult.getMessage(), (t2 - t1));
            throw throwable;
        }
    }


    private void getSystemLog(String ip, String userId, String url, int type, String result, long responseTime) {
        //无用户信息默认
        if (StringUtil.isEmpty(userId)) {
            userId = "null";
        }
        DsgSysOptLog dsgSysOptLog = new DsgSysOptLog();
        dsgSysOptLog.setOid(UUIDGenerator.getUUID());
        //ApplyId记录用户Id
        dsgSysOptLog.setOptUser(userId);
        dsgSysOptLog.setActTime(new Date());
        dsgSysOptLog.setClientIp(ip);
        dsgSysOptLog.setMethod(url);
        dsgSysOptLog.setResTime(responseTime);
        dsgSysOptLog.setOptType(type);
        dsgSysOptLog.setOptContent(result);
        writeLog(dsgSysOptLog);
    }


    /**
     * 获取方法RequestMapping中的value
     */
    private String getUri(MethodInvocation invocation) {
        StringBuffer uri = new StringBuffer();
        Method method = invocation.getMethod();
        Class clazz = method.getDeclaringClass();
        //判断是否存在requestMapping注释
        boolean present1 = clazz.isAnnotationPresent(RequestMapping.class);
        if (present1) {
            //得到requestMapping注释
            RequestMapping annotation2 = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            if (annotation2 != null) {
                String[] value = annotation2.value();
                if (value != null && value.length > 0) {
                    uri.append(value[0]);
                }
            }
        }
        //判断是否存在requestMapping注释
        boolean present = method.isAnnotationPresent(RequestMapping.class);
        if (present) {
            //得到requestMapping注释
            RequestMapping annotation = method.getAnnotation(RequestMapping.class);
            String[] value = annotation.value();
            if (value != null && value.length > 0) {
                uri.append(value[0]);
            }
        }
        return uri.toString();
    }


    /**
     * 记录操作日志
     */
    private void writeLog(DsgSysOptLog dsgSysOptLog) {
        try {
            if (dsgSysOptLogService == null) {
                log.info("dsgSysOptLog is null!!!");
                BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(ServletUtils.getRequest().getServletContext());
                dsgSysOptLogService = (DsgSysOptLogServiceImpl) factory.getBean("dsgSysOptLogService");
            }
            dsgSysOptLogService.save(dsgSysOptLog);
        } catch (Throwable e) {
            log.error("writeLog() err!", e);
        }
    }
}
